<script setup lang="ts">
import { reactive, ref, onMounted, nextTick, computed, watch } from 'vue'
import { getInfoAPI, getSearchXGPTINFO } from '@/api/search/index'
import type { AxiosResponse } from 'axios'
import { assignObject } from '@/utils/object'
import { HttpCodeEnum } from '@packages/share/enums'
import { ElMessage, ElDialog ,vLoading} from 'element-plus'
import AMAP from '@/views/modules/search/components/Amap.vue'
import hljs from 'highlight.js'
import Vditor from 'vditor';
import 'vditor/dist/index.css';
import 'highlight.js/styles/github-dark.css';

const props = defineProps({
  id: {
    type: String,
    required: true,
    default: () => { }
  }
})
const AmapRef = ref()
const infos = reactive({
  ip: '',
  type: '',
  port_num: null,
  serve_num: null,
  app_num: null,
  loophole_num: null,
  location: '',
  longitude: '',
  latitude: '',
  system: '',
  updateTime: ''
})
// GPT头部栏状态
const NavNotEmpty = computed(() => {
  return Object.entries(XGPTKEY.value).length !== 0;
});
// Vditor盒子
const VRef = ref()
// Vditor实例
const vditorInstance = ref();
// loading状态
const loadFlag = ref(false)
// GPT抽屉状态
const XGPVisible = ref()
// GPT请求参数
const XGPTKEY = ref()
// GPT输出字符
const outStr = ref('')
// GPT正在执行(防止请求期间关闭dialog重新请求)
const IsGptFlag = ref(false)

const getInfo = (id: string) => {
  getInfoAPI(id).then((res: AxiosResponse) => {
    const { data, code, message } = res.data
    if (code === HttpCodeEnum.SUCCESS) {
      assignObject(infos, data)
      nextTick(() => {
        AmapRef.value.init(data.latitude, data.longitude)
      })
    } else ElMessage.error(message)
  })
  getSearchXGPTINFO(id).then((res: AxiosResponse) => {
    const { data, code, message } = res.data
    if (code === HttpCodeEnum.SUCCESS) {
      XGPTKEY.value = data
    } else ElMessage.error(message)
  })
}
// XGPT解读
const XGPT = () => {
  XGPVisible.value = true
  if (IsGptFlag.value === true) return
  loadFlag.value = true
  outStr.value = ''
  // if (outStr.value.length > 0) {
  //   loadFlag.value = false
  //   return
  // }

  fetch(`cy/asset/getAssetGpt`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ ...XGPTKEY.value }) // 只传递一次参数
  })
    .then(async (response: any) => {
      const reader = response.body.getReader()
      const decoder = new TextDecoder()
      loadFlag.value = false
      IsGptFlag.value = true
      while (true) {
        const { done, value } = await reader.read()
        if (done) {
          console.log("传输完成!!!");
          break
        }
        let text = decoder.decode(value, { stream: true }).replace(/data:/g, '').replace(/(\[DONE\])?/g, '').trim();
        const contentMatch = text.match(/"content":"([^"]+)"/);//返回数据是字符串
        if (contentMatch && contentMatch[1]) {
          const contentValue = contentMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"'); // 处理转义字符
          outStr.value += contentValue
          if (vditorInstance.value) {
            vditorInstance.value.setValue(outStr.value);
          }
        }

      }
    })
    .catch((error) => {
      console.error('连接错误:', error)
      loadFlag.value = false
    })
    .finally(() => {
      IsGptFlag.value = false
    })
}


const VitorInit = () => {
  nextTick(() => {
    if (VRef.value) {
      vditorInstance.value = new Vditor(VRef.value, {
        height: 450,
        value: outStr.value,
        cache: {
          enable: false,
          id: 'VditorValue',
        },
        preview: {
          hljs: {
            enable: true,
            style: "github-dark",
            lineNumber: true,
          }
        },
        toolbar: [],
        after: () => {
          console.log('Vditor is ready');
        },
      });
    }
  });
}
watch(XGPVisible, (newVal) => {
  if (newVal) {
    // 弹窗显示时初始化 Vditor
    nextTick(() => {
      VitorInit();
    });
  } else {
    // 弹窗关闭时销毁 Vditor
    if (vditorInstance.value) {
      vditorInstance.value.destroy();
      vditorInstance.value = null;
    }
  }
});
onMounted(() => {
  getInfo(props.id)
})
</script>

<template>
  <div class="basepage flex">
    <!-- 地图 -->
    <div class="map jm-bg-color">
      <AMAP ref="AmapRef" v-model:title="infos.ip" />
    </div>
    <!-- 展示信息 -->
    <div class="infobox">
      <div class="nav flex">
        <div class="title">{{ id }}</div>
        <jm-tag class="XGPT" @click.stop="XGPT()">GPT解读</jm-tag>
      </div>

      <div class="desbox flex">
        <jm-descriptions :column="2" :border="true">
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">IP</div>
            </template>
            {{ infos.ip }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">操作系统</div>
            </template>{{ infos.system }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">类型</div>
            </template>{{ infos.type }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">国家</div>
            </template>
            {{ infos.location }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">坐标</div>
            </template>
            {{ `${infos.longitude},${infos.latitude}` }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">最新更新时间</div>
            </template>
            {{ infos.updateTime }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">端口数</div>
            </template>
            {{ infos.port_num }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">服务数</div>
            </template>
            {{ infos.serve_num }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">应用数</div>
            </template>
            {{ infos.app_num }}
          </jm-descriptions-item>
          <jm-descriptions-item>
            <template #label>
              <div class="cell-item">漏洞数</div>
            </template>
            {{ infos.loophole_num }}
          </jm-descriptions-item>
        </jm-descriptions>
      </div>
    </div>
    <!-- XGPT解读 -->
    <el-dialog class="GPTDialog" v-model="XGPVisible" :modal="true" title="资产解读">
      <div class="GPTBox">
        <!-- 头部显示 -->
        <div class="GPTNav flex" v-if="NavNotEmpty">
          <span class="nav-text" style="flex: 1;">端口：{{ XGPTKEY.port }}</span>
          <span class="nav-text" style="flex: 1;">服务：{{ XGPTKEY.service }}</span>
          <span class="nav-text" style="flex: 1;">设备类型：{{ ['unknown', 'null'].includes(XGPTKEY.webServer) ? ''
            : XGPTKEY.webServer }}</span>
        </div>
        <!-- loading -->
        <div class="XGPTLoading" v-loading="loadFlag" v-if="loadFlag"></div>
        <!-- 加载内容 -->
        <div class="XGPTText" ref="VRef" v-show="!loadFlag"></div>
      </div>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
.map {
  width: 26%;
  height: 15.625rem;
}

.GPTDialog {
  .GPTBox {
    width: 100%;
    height: 500px;
    overflow: hidden;
    padding: 0 1rem;

    .GPTNav {
      padding: 0 1.25rem;
      margin-bottom: .5rem;
      height: 1.875rem;
      line-height: 1.875rem;
      font-weight: 700;
      font-size: 1.1rem;
      color: #333;
    }

    .XGPTLoading {     height: 100%;
      justify-content: center;
      align-items: center;
    }

    .XGPTText {
      white-space: pre-wrap;
      background-color: #f5f6f8;
      overflow: auto;

      :deep(strong) {
        font-weight: 600;
      }
    }
  }
}

.infobox {
  margin-left: 0.9375rem;
  flex: 1;

  .nav {
    height: 2.8125rem;
    padding-left: 0.5rem;
    background-color: #e0eafc;
    align-items: center;

    .XGPT {
      color: #666;
      background-color: #eef3fc;
      margin-left: 0.5rem;
      border: 1px solid #eef3fc;
      border-radius: 0.3rem;
      font-size: 14px;
      line-height: 14px;
      cursor: pointer;

      &:hover {
        color: #0d7cf2;
      }
    }

    .title {
      font-size: 1.4rem;
      font-weight: 700;
      color: #6e6e6e;
    }
  }

  .desbox {
    height: 12.8125rem;
    align-items: center;

    .el-descriptions {
      flex: 1;
    }

    .cell-item {}
  }
}
</style>
